const std = @import("std");
const cpu = @import("cpu.zig");

// 中断向量号定义
pub const IRQ_TIMER = 32;
pub const IRQ_KEYBOARD = 33;
pub const IRQ_SERIAL = 36;

// 中断描述符结构
const InterruptDescriptor = packed struct {
    offset_low: u16,
    segment_selector: u16,
    ist: u3,
    _reserved1: u5,
    gate_type: u4,
    _reserved2: u1,
    privilege_level: u2,
    present: u1,
    offset_mid: u16,
    offset_high: u32,
    _reserved3: u32,
};

// IDT（中断描述符表）结构
const InterruptDescriptorTable = struct {
    descriptors: [256]InterruptDescriptor,
};

// 中断处理程序类型
const InterruptHandler = fn() callconv(.C) void;

// 中断和异常处理程序
pub const TrapHandler = struct {
    idt: InterruptDescriptorTable align(16) = undefined,
    interrupt_handlers: [256]?InterruptHandler = [_]?InterruptHandler{null} ** 256,
    allocator: std.mem.Allocator,

    // 初始化中断处理器
    pub fn init(allocator: std.mem.Allocator) !TrapHandler {
        var handler = TrapHandler{
            .allocator = allocator,
        };
        return handler;
    }

    // 设置中断处理程序
    pub fn setInterruptHandler(self: *TrapHandler, irq: u32, handler: u64) !void {
        if (irq >= 256) {
            return error.InvalidInterruptVector;
        }

        // 在实际系统中，这里会设置IDT中的中断描述符
        std.log.info("Setting interrupt handler for IRQ {} to address {x}", .{irq, handler});

        // 将处理程序地址存储起来（模拟）
        // 注意：在实际系统中，这会涉及到更复杂的设置
        const func_ptr = @intToPtr(InterruptHandler, handler);
        self.interrupt_handlers[irq] = func_ptr;
    }

    // 设置中断处理表
    pub fn setupInterrupts(self: *TrapHandler) !void {
        // 初始化IDT
        std.log.info("Initializing Interrupt Descriptor Table");

        // 在实际系统中，这里会填充IDT并加载它
        // lidt指令会在这里执行

        // 初始化一些常用的中断处理程序
        try self.setupCommonInterruptHandlers();

        std.log.info("Interrupts setup completed");
    }

    // 设置常用的中断处理程序
    fn setupCommonInterruptHandlers(self: *TrapHandler) !void {
        // 设置时钟中断处理程序
        try self.setInterruptHandler(IRQ_TIMER, @ptrToInt(&timerInterruptHandler));

        // 设置键盘中断处理程序
        try self.setInterruptHandler(IRQ_KEYBOARD, @ptrToInt(&keyboardInterruptHandler));
    }

    // 触发中断（用于测试或软件中断）
    pub fn triggerInterrupt(self: *TrapHandler, irq: u32) !void {
        if (irq >= 256) {
            return error.InvalidInterruptVector;
        }

        std.log.info("Triggering interrupt {}", .{irq});

        // 在实际系统中，这里会执行int指令或其他方式触发中断
        if (self.interrupt_handlers[irq]) |handler| {
            handler();
        }
    }

    // 处理异常
    pub fn handleException(self: *TrapHandler, vector: u32, error_code: u64) void {
        std.log.info("Handling exception: vector={}, error_code={x}", .{vector, error_code});

        // 根据异常类型执行不同的处理
        switch (vector) {
            0 => std.log.err("#DE: Divide Error"),
            1 => std.log.err("#DB: Debug"),
            2 => std.log.err("NMI: Non-Maskable Interrupt"),
            3 => std.log.err("#BP: Breakpoint"),
            4 => std.log.err("#OF: Overflow"),
            5 => std.log.err("#BR: Bound Range Exceeded"),
            6 => std.log.err("#UD: Invalid Opcode"),
            7 => std.log.err("#NM: Device Not Available"),
            8 => std.log.err("#DF: Double Fault, error_code={x}", .{error_code}),
            // 其他异常处理...
            else => std.log.err("Unknown exception: {}", .{vector}),
        }

        // 在实际系统中，这里可能会尝试恢复或进入调试模式
        // 对于严重错误，可能需要停机
        cpu.halt();
    }

    // 清理资源
    pub fn deinit(self: *TrapHandler) void {
        // 禁用所有中断
        cpu.disableInterrupts();
        std.log.info("Trap handler deinitialized");
    }
};

// 时钟中断处理程序（示例）
fn timerInterruptHandler() callconv(.C) void {
    std.log.info("Timer interrupt received");

    // 在实际系统中，这里会：
    // 1. 向PIC发送EOI（End Of Interrupt）信号
    // 2. 更新系统时间
    // 3. 处理进程调度（如果需要）
}

// 键盘中断处理程序（示例）
fn keyboardInterruptHandler() callconv(.C) void {
    std.log.info("Keyboard interrupt received");

    // 在实际系统中，这里会：
    // 1. 从键盘控制器读取扫描码
    // 2. 将扫描码转换为ASCII字符
    // 3. 将字符放入输入缓冲区或通知相关进程
    // 4. 向PIC发送EOI信号
}

// 全局中断处理器实例（用于API访问）
pub var global_trap_handler: TrapHandler = undefined;